<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import dayjs from 'dayjs';
import type { DocMenuConfigT } from '@/@types/type-doc-menu.ts';
import { useLocale } from '@/composables/useLocale.ts';
import { ODropdown, ODropdownItem, OIcon, OIconChevronDown, OIconChevronRight, OPagination } from '@opensig/opendesign';
import AppEmpty from '@/components/AppEmpty.vue';
import { searchDocsApi } from '@/api/api-search.ts';
import { useData, useRouter } from 'vitepress';
import ResultContent from '@/components/search/ResultContent.vue';
import { useSearchingStore } from '@/stores/common.ts';
import { storeToRefs } from 'pinia';
import { useMenuStore } from '@/stores/menu.ts';
import { openWindow } from '@/utils/common.ts';

const searchStore = useSearchingStore();
const { keyword } = storeToRefs(searchStore);
const menuStore = useMenuStore();
const { categoryMap } = storeToRefs(menuStore);
// -------------------- 路径处理 --------------------
const { locale } = useLocale();
const getBreadcrumb = (path: string) => {
  const find = docsMenuList.value.find((item) => item.path === `/${ path }`);
  return find?.labels || [];
};
const handleMenus = () => {
  const leafNodes: any[] = [];
  const traverse = (node: DocMenuConfigT, path: string = '', labels: string[] = []) => {
    const currentLabel = [...labels, node.label];
    const currentPath = `${ path }/${ node.id }`;
    if (!node.children) {
      leafNodes.push({
        labels: currentLabel,
        path: currentPath,
      });
    } else {
      node.children.forEach((child) => {
        traverse(child, currentPath, currentLabel);
      });
    }
  };
  Object.values(categoryMap.value).forEach((item) => {
    item.config.forEach((child) => {
      traverse(child, item.base);
    });
  });
  return leafNodes;
};

const docsMenuList = computed(() => {
  return handleMenus();
});
// -------------------- 搜索 --------------------
const list = ref([]); // 搜索结果
const sortableList = [
  {
    label: '最相关降序排列',
    key: 'relation',
  },
  {
    label: '最新时间降序排列',
    key: 'orderTime',
  },
];
const sortType = ref('relation');
const current = ref(1); // 当前页
const size = ref(10); // 每页条数
const total = ref(110);
const changePage = ({ page, pageSize }: { page: number; pageSize: number }) => {
  current.value = page;
  size.value = pageSize;
  getResult();
};
const { page } = useData();
const params = computed(() => {
  const filePath = page.value.filePath;
  const docsType = filePath.split('/')[1];
  let params = {
    keyword: keyword.value,
    lang: locale.value,
    page: current.value,
    pageSize: size.value,
    type: 'docs',
    filter: [{ docsType }],
  };
  if (sortType.value === 'orderTime') {
    params['orderTime'] = 'desc';
  }
  return params;
});
const changeOrderType = (key: string) => {
  if (sortType.value === key) {
    return;
  }
  sortType.value = key;
  current.value = 1;
  getResult();
};
watch(
  () => params.value,
  () => {
    current.value = 1;
    getResult();
  },
  { deep: true },
);

const getResult = async () => {
  try {
    searchStore.setIsLoading(true);
    const res = await searchDocsApi(params.value);
    list.value = res.records || [];
    total.value = res.count || 0;
  } finally {
    searchStore.setIsLoading(false);
  }
};

onMounted(() => {
  getResult();
});

const router = useRouter();
const toDetail = (path: string) => {
  searchStore.setIsSearching(false);
  searchStore.setKeyword('');
  if (path.startsWith('http')) {
    openWindow(path, '_self');
  } else {
    router.go('/' + path);
  }
};

// 上报点击搜索结果事件
const reportClickResult = (e: MouseEvent) => {
  return {
    service: 'search_docs',
    properties: {
      type: 'result',
      keyword: searchStore.keyword,
      target: (e.currentTarget as HTMLElement).querySelector('.item-title')!.textContent,
      $url: location.href
    }
  };
};
</script>

<template>
  <div class="search-result">
    <div class="search-header">
      <div class="search-title">搜索结果</div>
      <div class="search-sort">
        <ODropdown trigger="hover">
          <span>{{ sortableList.find((v) => v.key === sortType)?.label || sortType }}</span>
          <OIcon>
            <OIconChevronDown></OIconChevronDown>
          </OIcon>
          <template #dropdown>
            <ODropdownItem v-for="t in sortableList" :key="t.key" :value="t.key" @click="() => changeOrderType(t.key)">{{ t.label }} </ODropdownItem>
          </template>
        </ODropdown>
      </div>
    </div>
    <template v-if="list.length">
      <div class="search-total">找到“{{ total }}”个结果</div>
      <div>
        <div class="search-result-item" v-analytics="reportClickResult" v-for="(item, idx) in list" :key="idx" @click="toDetail(item.path)">
          <div class="item-title highlight-wrapper" v-dompurify-html="item.title"></div>
          <div class="item-content">
            <ResultContent :content="item.textContent" />
          </div>
          <div class="item-desc">
            <div class="desc-path">
              <span>来自：</span>
              <template v-for="(t, tIdx) in getBreadcrumb(item.path)" :key="tIdx">
                <OIcon v-if="tIdx !== 0">
                  <OIconChevronRight></OIconChevronRight>
                </OIcon>
                <span>{{ t }}</span>
              </template>
            </div>
            <div class="desc-update" v-show="item.date">
              <span>更新时间：</span>
              <span>{{ dayjs(item.date).format('YYYY/MM/DD') }}</span>
            </div>
          </div>
        </div>
      </div>
      <OPagination :page="current" :pageSize="size" :total="total" @change="changePage"
                   :pageSizes="[10, 20, 50]"></OPagination>
    </template>
    <div class="search-empty" v-else>
      <AppEmpty>
        <template #description>未找到相关内容，请尝试其他搜索词</template>
      </AppEmpty>
    </div>
  </div>
</template>

<style scoped lang="scss">
.search-result {
  min-height: calc(var(--layout-content-min-height) - 204px);
  @include tip1;

  .o-icon {
    font-size: 16px;
  }

  .search-header {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .search-title {
      @include h1;
      font-weight: 500;
      color: var(--o-color-info1);
    }

    .search-sort .o-dropdown {
      cursor: pointer;
      color: var(--o-color-info1);
      display: flex;
      align-items: center;
      justify-content: space-between;

      .o-icon {
        margin-left: var(--o-gap-2);
      }
    }
  }

  .search-total {
    margin-top: var(--o-gap-2);
    margin-bottom: var(--o-gap-8);
    color: var(--o-color-info3);
  }

  .search-result-item {
    cursor: pointer;

    & + .search-result-item {
      margin-top: var(--o-gap-6);
    }

    @include hover {
      .item-title {
        color: var(--o-color-ubmc-hover);
        :deep(span) {
          color: var(--o-color-ubmc-hover);
        }
      }
    }

    .item-title {
      @include text2;
      font-weight: 500;
      color: var(--o-color-info1);
      @include hover {
        color: var(--o-color-ubmc-hover);
        :deep(span) {
          color: var(--o-color-ubmc-hover);
        }
      }
    }

    .item-content {
      margin-top: var(--o-gap-3);
    }

    .item-desc {
      margin-top: var(--o-gap-2);
      color: var(--o-color-info3);
      display: flex;
      align-items: center;
      justify-content: space-between;
      @include tip2;

      & > div {
        display: flex;
        align-items: center;
        column-gap: var(--o-gap-2);
      }
    }
  }

  .o-pagination {
    margin-top: var(--o-gap-4);
    display: flex;
    justify-content: flex-end;
  }

  .search-empty {
    padding: 220px 0;
    @include respond-to('<=pad_v') {
      padding: 120px 0;
    }
  }
}
</style>
